/**
 * Socket.io 全局单例事件工具 for Vue 2
 * 提供全局单例Socket连接，可以在各个组件中使用
 * 注意：需要先在index.html中引入socket.io.min.js
 */
import { getSocketUrl } from '@/api/system'

// 用于存储全局唯一实例
let _singleton = null

// Socket URL将从API获取
let SOCKET_URL = null

// 默认Socket URL，可在使用时覆盖
// 开发环境使用相对路径让代理生效，生产环境直接连接外部WebSocket服务


/**
 * 创建并返回Socket单例
 * @param {String} url Socket服务URL
 * @param {Object} options Socket.io配置选项
 * @returns {Object} Socket工具对象
 */
export default function useSocket(url, options = {}) {
  // 已有单例就直接返回
  if (_singleton) return _singleton

  // 状态对象（Vue 2中不使用ref，直接用对象）
  const state = {
    socket: null,
    connected: false,
    connecting: false,
    error: null,
    listeners: new Map()
  }

  // 连接方法
  const connect = async() => {
    // 如果已经在连接中，直接返回
    if (state.connecting) {
      console.log('[Socket] 正在连接中，跳过重复连接')
      return
    }

    // 如果已经连接且socket存在，先断开
    if (state.socket?.connected) {
      console.log('[Socket] 检测到已连接，先断开旧连接')
      state.socket.disconnect()
      state.socket = null
    }

    if (typeof window === 'undefined' || !window.io) {
      state.error = new Error('Socket.io 未加载，请确保已引入 socket.io.min.js')
      console.error('[Socket] 错误:', state.error)
      return
    }

    state.connecting = true
    state.error = null

    try {
      // 先获取Socket地址
      let socketUrl = SOCKET_URL
      if (!socketUrl) {
        console.log('[Socket] 正在从API获取Socket地址...')
        try {
          const response = await getSocketUrl()
          if (response && response.code === 1 && response.url) {
            socketUrl = response.url
            // eslint-disable-next-line require-atomic-updates
            SOCKET_URL = socketUrl // 缓存URL
            console.log('[Socket] 成功获取Socket地址:', socketUrl)
          } else {
            console.warn('[Socket] 获取Socket地址失败，使用默认地址')
            socketUrl = url 
            // eslint-disable-next-line require-atomic-updates
            SOCKET_URL = socketUrl // 缓存URL
          }
        } catch (error) {
          console.error('[Socket] 获取Socket地址异常:', error)
          console.warn('[Socket] 使用默认地址')
          socketUrl = url 
          // eslint-disable-next-line require-atomic-updates
          SOCKET_URL = socketUrl // 缓存URL
        }
      }

      console.log('[Socket] 开始连接，URL:', socketUrl)

      // 创建socket实例
      const newSocket = window.io(socketUrl, {
        transports: ['websocket', 'polling'],
        autoConnect: true,
        reconnection: true,
        reconnectionAttempts: 5,
        reconnectionDelay: 1000,
        reconnectionDelayMax: 5000,
        timeout: 20000,
        path: '/socket.io',
        ...options
      })

      // 内部状态管理 - 使用connect事件但不干扰外部监听
      // 注意：这里使用socket.io.on而不是socket.on，确保不影响外部监听器
      const originalOn = newSocket.on.bind(newSocket)

      // 监听connect事件来更新内部状态
      originalOn('connect', () => {
        console.log('[Socket内部状态] connect事件触发，Socket ID:', newSocket.id)
        state.connected = true
        state.connecting = false
        state.error = null
      })

      originalOn('connect_error', (err) => {
        console.error('[Socket内部状态] 连接错误:', err)
        state.connected = false
        state.connecting = false
        state.error = err
      })

      originalOn('disconnect', (reason) => {
        console.log('[Socket内部状态] 连接已断开，原因:', reason)
        state.connected = false
        state.connecting = false
      })

      originalOn('reconnect_failed', () => {
        console.log('[Socket内部状态] 重连失败')
        state.connecting = false
      })

      // 注册所有待注册的监听器
      console.log('[Socket] Socket实例已创建，注册待处理的监听器...')
      state.listeners.forEach((callbacks, event) => {
        callbacks.forEach(callback => {
          console.log('[Socket] 注册待处理监听器:', event)
          newSocket.on(event, callback)
        })
      })

      // 最后赋值给state.socket（避免竞态条件）
      // eslint-disable-next-line require-atomic-updates
      state.socket = newSocket
      console.log('[Socket] Socket实例准备完毕，等待连接...')
    } catch (err) {
      console.error('[Socket] 连接异常:', err)
      // eslint-disable-next-line require-atomic-updates
      state.connecting = false
      // eslint-disable-next-line require-atomic-updates
      state.error = err
    }
  }

  // 断开连接
  const disconnect = () => {
    if (!state.socket) {
      console.log('[Socket] Socket已断开或未创建')
      return
    }

    try {
      console.log('[Socket] 开始断开连接...')

      // 清理所有业务监听器
      if (state.listeners.size > 0) {
        state.listeners.forEach((arr, event) => {
          arr.forEach(cb => {
            try {
              if (state.socket) {
                state.socket.off(event, cb)
              }
            } catch (err) {
              console.warn('[Socket] 移除监听器失败:', event, err)
            }
          })
        })
        state.listeners.clear()
      }

      // 断开socket连接
      if (state.socket && typeof state.socket.disconnect === 'function') {
        state.socket.disconnect()
      }

      // 清理状态
      state.socket = null
      state.connected = false
      state.connecting = false

      console.log('[Socket] 断开连接完成')
    } catch (err) {
      console.error('[Socket] 断开连接异常:', err)
      // 即使出错也要清理状态
      state.socket = null
      state.connected = false
      state.connecting = false
    }
  }

  // 发送消息
  const emit = (event, ...args) => {
    // 检查socket是否存在
    if (!state.socket) {
      console.warn('[Socket] Socket未创建，无法发送消息:', event)
      return false
    }

    // 检查连接状态
    if (!state.connected) {
      console.warn('[Socket] Socket未连接，无法发送消息:', event)
      return false
    }

    // 检查socket是否有emit方法
    if (typeof state.socket.emit !== 'function') {
      console.error('[Socket] Socket对象无效，缺少emit方法')
      return false
    }

    try {
      state.socket.emit(event, ...args)
      console.log('[Socket] 已发送消息:', event, args.length > 0 ? args : '(无参数)')
      return true
    } catch (err) {
      console.error('[Socket] 发送消息异常:', err)
      console.error('[Socket] 事件:', event, '参数:', args)

      // 如果发送失败，可能是连接已断开，更新状态
      if (err.message && err.message.includes('disconnect')) {
        state.connected = false
        console.warn('[Socket] 检测到连接已断开，更新状态')
      }

      return false
    }
  }

  // 监听事件
  const on = (event, callback) => {
    // 先记录监听器
    if (!state.listeners.has(event)) {
      state.listeners.set(event, [])
    }

    const callbacks = state.listeners.get(event)

    // 检查是否已经存在，避免重复添加
    if (callbacks.includes(callback)) {
      console.log('[Socket] 监听器已存在，跳过:', event)
      return () => off(event, callback)
    }

    // 添加到记录中
    callbacks.push(callback)

    // 如果socket已创建，立即注册
    if (state.socket) {
      console.log('[Socket] 立即添加事件监听器:', event)
      state.socket.on(event, callback)
    } else {
      // 如果socket未创建，先存储回调，等socket创建后再注册
      console.log('[Socket] Socket未创建，存储监听器待注册:', event)
    }

    // 返回取消监听的函数
    return () => off(event, callback)
  }

  // 只监听一次
  const once = (event, callback) => {
    if (!state.socket) {
      console.warn('[Socket] Socket未创建，无法添加once监听器:', event)
      return
    }
    console.log('[Socket] 添加once监听器:', event)
    state.socket.once(event, callback)
  }

  // 取消事件监听
  const off = (event, callback) => {
    if (!state.socket) return

    if (callback) {
      state.socket.off(event, callback)
      const arr = state.listeners.get(event)
      if (arr) {
        const index = arr.indexOf(callback)
        if (index !== -1) {
          arr.splice(index, 1)
          console.log('[Socket] 移除事件监听器:', event)
        }
      }
      if (arr && arr.length === 0) {
        state.listeners.delete(event)
      }
    } else {
      state.socket.off(event)
      state.listeners.delete(event)
      console.log('[Socket] 移除所有事件监听器:', event)
    }
  }

  // 获取socket id
  const getSocketId = () => {
    return state.socket?.id || null
  }

  // 重置Socket URL（强制重新从API获取）
  const resetSocketUrl = () => {
    console.log('[Socket] 重置Socket URL')
    SOCKET_URL = null
  }

  // 单例对象内暴露接口
  _singleton = {
    // 状态
    get socket() { return state.socket },
    get connected() { return state.connected },
    get connecting() { return state.connecting },
    get error() { return state.error },

    // Socket URL管理
    resetSocketUrl,

    // 方法
    connect,
    disconnect,
    emit,
    on,
    once,
    off,
    getSocketId
  }

  return _singleton
}

// 创建默认实例（但不自动连接）
export const socketInstance = useSocket()

// 创建Vue插件
export const SocketPlugin = {
  install(Vue) {
    Vue.prototype.$socket = socketInstance
  }
}

